﻿/**
 * @file		dd_pmc_watchdog.h
 * @brief		Watchdog Timer driver
 * @note		None
 * @attention	None
 * 
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

/** @weakgroup dd_pmc_watchdog_overview
@{
	CM0 PMC - Watchdog Timer Driver.<br>
@}*//* --- end of dd_pmc_watchdog_overview */

/** @weakgroup dd_pmc_watchdog_sequence
@{
	- @ref Watchdog_basic_sequence
	- @ref Wdog_Sample_Basic
	@section Watchdog_basic_sequence	Watchdog Basic sequence
	@image html dd_pmc_watchdog_basic_sequence.png
	<br>
	@section Wdog_Sample_Basic			Sample of Watchdog(Basic sequence)
	The example of executing watchdog counter start to end is as follows.
	@code
	INT32	ret;								// Return value
	T_DD_PMC_WDOG_CTRL	wdog_ctrl;
	
	wdog_ctrl.wdog_load = 1000000000;					// 1000000000[count] = 10[s]
	wdog_ctrl.reset_enable = D_DD_PMC_WDOG_ENABLE_OFF;		// Reset disable
	wdog_ctrl.int_enable = D_DD_PMC_WDOG_ENABLE_ON;			// Interrupt enable
	wdog_ctrl.pIntCallback = Sample_Callback0;			// User's Callback function
	wdog_ctrl.pRawIntCallback = Sample_Callback1;		// User's Callback function
	
	Dd_PMC_Wdog_Init();
	
	ret = Dd_PMC_Wdog_Ctrl(&wdog_ctrl);
	if (ret != 0) {
		// ERROR
		return ;
	}
	
	// Please wait for more than 33 second code here. The callback is called.
	
	// Please use following API when the callback function is called.
	// (Even if the callback is not called, following API can be used)
	Dd_PMC_Wdog_Reload();
	@endcode

@}*//* --- end of dd_pmc_watchdog_sequence */

#ifndef _DD_PMC_WDOG_H_
#define _DD_PMC_WDOG_H_

/** @weakgroup dd_pmc_watchdog_definition
@{*/

#include "driver_common.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
/* Return value of watchdog timer processing result */
#define D_DD_PMC_WDOG_INPUT_PARAM_ERR	(D_DD_PMC_WDOG | D_DDIM_INPUT_PARAM_ERROR)	/**< Input Parameter Error */
#define D_DD_PMC_WDOG_OVERFLOW			(D_DD_PMC_WDOG | D_DDIM_OVERFLOW_ERR)		/**< Load value is overflow */

// General-purpose definition of register value (Effectiveness selection)
#define D_DD_PMC_WDOG_ENABLE_OFF						(0)		/**< OFF	*/
#define D_DD_PMC_WDOG_ENABLE_ON							(1)		/**< ON		*/

/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
// Nothing Special

/*----------------------------------------------------------------------*/
/* Structure  															*/
/*----------------------------------------------------------------------*/
/** Control value */
typedef struct {
	ULONG 		wdog_load;			/**< WdogLoad register.<br>
										 Value range : 0x00000000~0xFFFFFFFF						*/
	UCHAR 		reset_enable;		/**< WdogControl.RESEN : Enable Watchdog reset output.<br>
										 <ul><li>@ref D_DD_PMC_WDOG_ENABLE_OFF
											 <li>@ref D_DD_PMC_WDOG_ENABLE_ON</ul>						*/
	UCHAR 		int_enable;			/**< WdogControl.INTEN : Enable the interrupt event.<br>
										 <ul><li>@ref D_DD_PMC_WDOG_ENABLE_OFF
											 <li>@ref D_DD_PMC_WDOG_ENABLE_ON</ul>						*/
	VP_CALLBACK pIntCallback;		/**< Callback function called when interrupt is generated		*/
	VP_CALLBACK pRawIntCallback;	/**< Callback function called when raw interrupt is generated	*/
}T_DD_PMC_WDOG_CTRL;

/** Peripheral Identification */
typedef struct {
	USHORT		part_number;		/**< This identifies the peripheral. Value:0x805					*/
	UCHAR		designer;			/**< Designer. Value:0x41 (ARM Limited is 0x41, ASCII A.)			*/
	UCHAR		revision_number;	/**< Revision number of the peripheral. Value:0~15 (starts from 0.)	*/
	UCHAR		configuration;		/**< This is the configuration option of the peripheral. Value:0	*/
}T_DD_PMC_WDOG_PERI_IDENTIFICATION;

/*----------------------------------------------------------------------*/
/* Grobal Data															*/
/*----------------------------------------------------------------------*/
// Nothing Special

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
// Nothing Special


/* @} */	// dd_pmc_watchdog_definition group

/** @weakgroup dd_pmc_watchdog_api
@{*/
/*----------------------------------------------------------------------*/
/* Function																*/
/*----------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif

//---------------------------- driver section ----------------------------
/**
 * Initialize Watchdog Register.<br>
 * Default status : WdogControl = 0, WdogLoad = 0xFFFFFFFF.<br>
 */
extern 	VOID	Dd_PMC_Wdog_Init(VOID);

/**
 * Setting of common control variable for Watchdog Counter.
 * @param[in]	wdog_ctrl				: Watchdog Control value. See @ref T_DD_PMC_WDOG_CTRL
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Ctrl(T_DD_PMC_WDOG_CTRL* wdog_ctrl);

/**
 * Reload Watchdog Counter.
 */
extern	VOID	Dd_PMC_Wdog_Reload(VOID);

/**
 * Get value of WdogLoad register.
 * @param[out]	wdog_load				: Watchdog Load
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Load(ULONG* wdog_load);

/**
 * Get value of WdogValue register.
 * @param[out]	wdog_counter			: Watchdog Counter
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Counter(ULONG* wdog_counter);

/**
 * Get value of WdogControl register.
 * @param[out]	wdog_ctrl				: Watchdog Control value. See @ref T_DD_PMC_WDOG_CTRL
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Control(T_DD_PMC_WDOG_CTRL* wdog_ctrl);

/**
 * Get value of WdogRIS/WdogMIS register.
 * @param[out]	raw_wdog_int			: Raw Watchdog Interrupt
 * @param[out]	wdog_int				: Watchdog Interrupt
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Interrupt(UCHAR* raw_wdog_int, UCHAR* wdog_int);

/**
 * Get value of WdogLock register.
 * @param[out]	wdog_lock				: Lock status<br>
 * 										  <ul><li>D_DD_PMC_WDOG_ENABLE_OFF : Unlock
 * 											  <li>D_DD_PMC_WDOG_ENABLE_ON : Lock</ul>
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Lock(UCHAR* wdog_lock);

/**
 * Get value of WdogITCR register.
 * @param[out]	test_mode				: Integration Test Mode Enable
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Test_Mode(UCHAR* test_mode);

/**
 * Get value of WdogPeriphID0~3 register.
 * @param[out]	identification			: Peripheral Identification. See @ref T_DD_PMC_WDOG_PERI_IDENTIFICATION
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_Peri_Identification(T_DD_PMC_WDOG_PERI_IDENTIFICATION* identification);

/**
 * Get value of WdogPCellID0~3 register.
 * @param[out]	pcell					: PrimeCell Identification. Value:0xB105F00D
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Get_PCell_Identification(ULONG* pcell);

/**
 * Set value of WdogLoad register.
 * @param[in]	wdog_load				: Watchdog Load. Value range:0x00000000~0xFFFFFFFF
 * @retval	D_DDIM_OK						: Normal end
 */
extern	INT32	Dd_PMC_Wdog_Set_Load(ULONG wdog_load);

/**
 * Set value of WdogControl register.
 * @param[in]	wdog_ctrl				: Watchdog Control value. See @ref T_DD_PMC_WDOG_CTRL
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Set_Control(T_DD_PMC_WDOG_CTRL* wdog_ctrl);

/**
 * Clear Interrupt flag (Set WdogIntClr register).
 * @return	D_DDIM_OK						: Normal end
 */
extern	INT32	Dd_PMC_Wdog_Clear_Interrupt(VOID);

/**
 * Set value of WdogLock register. 
 * @param[in]	wdog_lock				: Watchdog Lock setting<br>
 * 										  <ul><li>D_DD_PMC_WDOG_ENABLE_OFF : Unlock
 * 											  <li>D_DD_PMC_WDOG_ENABLE_ON : Lock</ul>
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Set_Lock(UCHAR wdog_lock);

/**
 * Set value of WdogITCR/WdogITOP register.
 * @param[in]	test_mode				: Integration Test Mode Enable<br>
 * 										  <ul><li>D_DD_PMC_WDOG_ENABLE_OFF
 * 											  <li>D_DD_PMC_WDOG_ENABLE_ON</ul>
 * @param[in]	test_res				: Integration Test WDOGINT value<br>
 * 										  <ul><li>D_DD_PMC_WDOG_ENABLE_OFF
 * 											  <li>D_DD_PMC_WDOG_ENABLE_ON</ul>
 * @param[in]	test_int				: Integration Test WDOGRES value<br>
 * 										  <ul><li>D_DD_PMC_WDOG_ENABLE_OFF
 * 											  <li>D_DD_PMC_WDOG_ENABLE_ON</ul>
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 */
extern	INT32	Dd_PMC_Wdog_Set_Test_Mode(UCHAR test_mode, UCHAR test_res, UCHAR test_int);

/**
 * It is Interrupt Handler of Watchdog.<br>
 * The CallBack function is called.
 */
extern	VOID	Dd_PMC_Wdog_Int_Handler(VOID);

#ifdef CO_DDIM_UTILITY_USE
//---------------------------- utility section ---------------------------
/**
 * To input the value at the passed time to WDOG_LOAD, it converts it into the number of clocks.
 * @param[in]		wdog_wdmode			: Watchdog Mode
 * 										  <ul><li>0:Timer Mode
 * 											  <li>1:Watchdog Mode</ul>
 * @param[in]		msec				: Designated time(milli seconds)
 * @param[out]		convert_counter		: Value of converted msec
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 * @retval	D_DD_PMC_WDOG_OVERFLOW			: Load value is overflow
 * @remarks
 * In the watchdog mode, If PERIPHCLK is 100[MHz] and prescaler is max value(=0xFF), range is 1 to 10995116[msec].<br>
 * In the timer mode, If msec exceeded the maximum value of WDOG_LOAD(4294967295=0xFFFFFFFF) as a result of calculation, Dd_PMC_Wdog_Calculate uses soft counter.<br>
 * The soft counter enables the count that exceeds the maximum value.<br>
 * The counter maintains the value in which msec is divided by maximum value of WDOG_LOAD(4294967295).<br>
 * If soft counter maintains the value when timer is expired, WDOG_LOAD is reloaded by 0xFFFFFFFF and soft counter is decrement.<br>
 * If soft counter is zero and timer is expired, WDOG_LOAD is reloaded by remained number for msec divided by 4294967295.
 */
extern INT32 Dd_PMC_Wdog_Calculate(ULONG wdog_wdmode, ULONG msec, ULONG* convert_counter);

/**
 * The passed time to WDOG_LOAD to set the Watchdog timer, msec converts into the number of clocks. 
 * @param[in]		wdog_wdmode			: Watchdog Mode
 * 										  <ul><li>0:Timer Mode
 * 											  <li>1:Watchdog Mode</ul>
 * @param[in]		msec				: Designated time(milli seconds)
 * @retval	D_DDIM_OK						: Normal end
 * @retval	D_DD_PMC_WDOG_INPUT_PARAM_ERR	: Input Parameter Error
 * @retval	D_DD_PMC_WDOG_OVERFLOW			: Load value is overflow
 * @remarks
 * In the watchdog mode, If PERIPHCLK is 100[MHz] and prescaler is max value(=0xFF), range is 1 to 10995116[msec].<br>
 * In the timer mode, If msec exceeded the maximum value of WDOG_LOAD(4294967295=0xFFFFFFFF) as a result of calculation, Dd_PMC_Wdog_Calculate uses soft counter.<br>
 * The soft counter enables the count that exceeds the maximum value.<br>
 * The counter maintains the value in which msec is divided by maximum value of WDOG_LOAD(4294967295).<br>
 * If soft counter maintains the value when timer is expired, WDOG_LOAD is reloaded by 0xFFFFFFFF and soft counter is decrement.<br>
 * If soft counter is zero and timer is expired, WDOG_LOAD is reloaded by remained number for msec divided by 4294967295.
 */
extern	INT32 Dd_PMC_Wdog_Set_Timer(ULONG wdog_wdmode, ULONG msec);
#endif	// CO_DDIM_UTILITY_USE

#ifdef __cplusplus
}
#endif

/* @} */	// dd_pmc_watchdog_api group

#endif	// _DD_PMC_WDOG_H_
